﻿//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
//    Crolengi, this program (a part of program) is gameengine based on C++\Directx
//    Copyright (C) 2008 Pashinin Anton Alekseevich (Crol)
//
//    This program is free software: you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation, either version 3 of the License, or
//    (at your option) any later version.
//
//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.
//
//    You should have received a copy of the GNU General Public License
//    along with this program.  If not, see <http://www.gnu.org/licenses/>.
//    (INCLUDING NEGLIGENCE OR OTHERWISE) 
//    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 
//    EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//    Contacts: 
//    Mail: crolengi@gmail.com
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///// КЛАССЫ ОЪЕКТОВ
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////[include]///////////////////////////////////////////////////////
#ifndef  GObject_h
#define  GObject_h
#include <d3d9.h>
#include <d3dx9.h>
#include "CLREngi_main_class.h"
#include "CRLEngi_strings_lib\\CRLEngi_strings.h"
#include "CRLEngi_trees_params_lib\\CRLEngi_trees_params.h"

#pragma warning( disable : 4996 ) // disable deprecated warning  
#include <strsafe.h>              
#pragma warning( default : 4996 ) 

#define _CRT_SECURE_NO_DEPRECATE

/////////////////////////////////////////////////////[СТРУКТУРЫ]/////////////////////////////////////////////////// 
struct TRIANGLE // структура треугольника сетки
{
	D3DXVECTOR3 v0;  // три точки
	D3DXVECTOR3 v1;
	D3DXVECTOR3 v2;
	D3DXVECTOR3  N;  // вектор нормали
	float        d;  // точка центра треугольника
};

//////////////////////////////////////////////////////[КЛАСС]//////////////////////////////////////////////////////
///// 
/////  СТАНДАРТНЫЙ КЛАСС ДЛЯ ОБЪЕКТОВ  class MAIN_CGObject
///// 
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class CLREngi_Object_Super
{
////////////////////////////////////////////////////[переменные]/////////////////////////////////////////////////// 
protected:
CLREngi                 Engi;

LPDIRECT3DDEVICE9       *pd3dDevice    ;   // Our rendering device
LPD3DXMESH              pMesh          ;   // собственно сетка объекта
D3DMATERIAL9*           pMeshMaterials ;   // материалы объекта
LPDIRECT3DTEXTURE9*     pMeshTextures  ;   // текстуры объекта
DWORD                   dwNumMaterials ;   // число материалов объекта

ResourceManeger         *ResManager;

D3DXMATRIX PmatWorld;
D3DXMATRIX PmatScale;

/////////////////////////////////////////////////////[ПЕРЕМЕННЫЕ]////////////////////////////////////////////////// 
public:
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////  матрицы
D3DXMATRIXA16           GOMatrix; // клон мировой матрицы
D3DXMATRIX           GOMatrixDef; // матрица объекта
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 

    int id;         // Идентификатор объекта
	MAIN_CGObject *next; // Указатель на следующий узел списка
	MAIN_CGObject *prev; // Указатель на предыдущий узел списка
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
////////параметры считанные из файла: *-пока не использованы
		char         filename[256];   // имя модели
        char         modelFile[256];  //*путь у модели
		char         textureFile[256];//*путь к текстуре
		float        xcoord;          // координата
		float        ycoord;          // координата
		float        zcoord;          // координата
		char         effectsP[256];   //*эффекты модели (для шейдеров)
		int          alpha;           // прозрачность (при 0 объект навечно станет невидим)
		int          bump;            //*есть ли bump (1 или 0)
		int          physix;          // параметр физики (11 - статичный физический)
		float        mass;            //*масса объекта
        D3DXVECTOR3  box;

/////////////////////////////////// (шейдеры из файла) ///////////////////////////////////////////////////////////
	ID3DXEffect *aEffect[20];
	char EffectsList[20][256];     // массив эффектов модели (грузится спец функцией чтения)
	char TechniqueList[20][256];   // массив техник отображения (соответстующих EffectsList)
	char ParamTypeList[20][256];   // массив формата параметров эффектов (соответстующих EffectsList)
	int  EffectsLoaded;            // число загруженных эффектов

	LPDIRECT3DTEXTURE9      g_pTexture ;               // Our texture 1
    LPDIRECT3DTEXTURE9      g_pReflectionTexture ;     // Our texture 1

	LPDIRECT3DTEXTURE9 diffuse_texture;                 // текстура объекта
	LPDIRECT3DTEXTURE9 reflection_texture;              // карта отражения
	LPDIRECT3DTEXTURE9 bump_texture;                    // бамп карта
	LPDIRECT3DTEXTURE9 height_texture;                  // карта высот

	LPDIRECT3DCUBETEXTURE9 reflection_textureCube;      // карта отражения

	D3DLIGHT9 *light;

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////                                        внутренние функции
////////////////////////////////////////////////////[ФУНКЦИИ]//////////////////////////////////////////////////////
protected:
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                функция установки матрицы в новую точку
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////	
void GOMatrixTranslateDef(D3DXMATRIX *matr){
	D3DXMatrixTranslation(matr,xcoord,ycoord,zcoord);	
	}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////                                       глобальные функции
////////////////////////////////////////////////////[ФУНКЦИИ]//////////////////////////////////////////////////////
public:
const D3DXMATRIX& GetWorldPos() const {return GOMatrixDef;}
void SetWorldPos(D3DXMATRIX* matrix) {GOMatrixDef = *matrix;}
void Positioning(){(*pd3dDevice)->SetTransform( D3DTS_WORLD, &GetWorldPos());}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////                                Функция загрузки сетки и текстур к ней
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT InitGeometry(LPCSTR filename,D3DLIGHT9 *MAIN_Light)
{   

	D3DXCreateTextureFromFile(*pd3dDevice, "textures\\stones.bmp", &g_pTexture ); 
	D3DXCreateTextureFromFile(*pd3dDevice, "textures\\Default_reflection.dds", &g_pReflectionTexture );


	LPD3DXBUFFER pD3DXMtrlBuffer;
      //грузим сетку
    if( FAILED( D3DXLoadMeshFromX( filename, D3DXMESH_SYSTEMMEM, 
                                   *pd3dDevice, NULL, 
                                   &pD3DXMtrlBuffer, NULL, &dwNumMaterials, 
                                   &pMesh ) ) )
    {

		char a[256] ="\0";
		strcat(a,"не найдена модель: ");
		strcat(a,filename);
        MessageBox(NULL, a, "game.exe", MB_OK);

		// если нет файла модели грузим стандартную
		if( FAILED( D3DXLoadMeshFromX( "blank.x", D3DXMESH_SYSTEMMEM, 
                                              *pd3dDevice, NULL, 
                                              &pD3DXMtrlBuffer, NULL, &dwNumMaterials, 
                                              &pMesh ) ) )
         {   return E_FAIL;  }
    }

    //// Получаем материал и его параметры отловив параметры через
    //   pD3DXMtrlBuffer

	//проверяем видимый объект или нет
	if (alpha!=0)
	{
    D3DXMATERIAL* d3dxMaterials = (D3DXMATERIAL*)pD3DXMtrlBuffer->GetBufferPointer();
    pMeshMaterials = new D3DMATERIAL9[dwNumMaterials];
    if( pMeshMaterials == NULL )
        return E_OUTOFMEMORY;
    pMeshTextures  = new LPDIRECT3DTEXTURE9[dwNumMaterials];
    if( pMeshTextures == NULL )
        return E_OUTOFMEMORY;

    for( DWORD i=0; i<dwNumMaterials; i++ )
    {
        // Copy the material
        pMeshMaterials[i] = d3dxMaterials[i].MatD3D;

        // Set the ambient color for the material (D3DX does not do this)
        pMeshMaterials[i].Ambient = pMeshMaterials[i].Diffuse;

        pMeshTextures[i] = NULL;
        if( d3dxMaterials[i].pTextureFilename != NULL && 
            lstrlenA(d3dxMaterials[i].pTextureFilename) > 0 )
        {
            // Create the texture
            if( FAILED( D3DXCreateTextureFromFileA( *pd3dDevice, 
                                                d3dxMaterials[i].pTextureFilename, 
                                                &pMeshTextures[i] ) ) )
            {
                // If texture is not in current folder, try parent folder
                const CHAR* strPrefix = "textures\\";
                CHAR strTexture[MAX_PATH];
                StringCchCopyA( strTexture, MAX_PATH, strPrefix );
                StringCchCatA( strTexture, MAX_PATH, d3dxMaterials[i].pTextureFilename );
                // If texture is not in current folder, try parent folder
                if( FAILED( D3DXCreateTextureFromFileA( *pd3dDevice, 
                                                    strTexture, 
                                                    &pMeshTextures[i] ) ) )
                {
                       if( FAILED( D3DXCreateTextureFromFileA( *pd3dDevice, 
                                  "blank.bmp", 
                                  &pMeshTextures[i] ) ) )
                          {
					        MessageBox(NULL, strTexture, "game.exe", MB_OK);//"Could not find texture map"
					      }
				 }
            }
        }
    }

	}//->(alpha!=0)

    // Done with the material buffer
    pD3DXMtrlBuffer->Release();

   //(*pd3dDevice)->SetTransform( D3DTS_WORLD, &GOMatrixDef);

   GOMatrixTranslateDef(&GOMatrixDef);

   //if (EffectsLoaded>0) EffectsPreporation_loading();

	return S_OK;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////                    Функция общего рендера и выбора типа рендера для отображения объекта
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*void	MAIN_GORender(D3DXVECTOR3 *camera_pos)
{
	Positioning();
	// через if выбираем тип рендера
	if(alpha>100)
	GORender_NOSHADER_ALPHA();
	else if (EffectsLoaded==0)
	GORender_NOSHADER_NOALPHA();
	else
	GORender_SHADER_NOALPHA(camera_pos);
}*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////                        Функция рендера объекта без шейдеров и без прозрачности
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void    GORender_NOSHADER_NOALPHA() 
{//Positioning();
	 (*pd3dDevice)->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
	 (*pd3dDevice)->SetRenderState( D3DRS_ALPHABLENDENABLE,FALSE );
	 for( DWORD i=0; i<dwNumMaterials; i++ )
	 {
		// Set the material and texture for this subset

			
			if (diffuse_texture!=NULL)
			{
				(*pd3dDevice)->SetMaterial( &pMeshMaterials[i] );
				(*pd3dDevice)->SetTexture( 0, diffuse_texture );
			}
			else
			{
				(*pd3dDevice)->SetMaterial( &pMeshMaterials[i] );
				(*pd3dDevice)->SetTexture( 0, pMeshTextures[i] );
			}
	
		// draw subset
	 pMesh->DrawSubset( i );
     }//->for

}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////                                        функции поворота объекта
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void    rotateYL(float timeFactor)
{
D3DXMatrixRotationY( &GOMatrixDef, timeGetTime()/timeFactor );
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                                  КОНСТРУКТОР
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public:
CLREngi_Object_Super   (CLREngi E,D3DXMATRIXA16* matrix)
{
	Engi = E;            // получаем 3д девайс
    //GOMatrixDef = *matrix;             // получаем мировую матрицу проекции
	D3DXMatrixIdentity(&GOMatrix);  // обрабатываем созданную матрицу

	
   
};
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                                   ДЕСТРУКТОР
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
virtual ~CLREngi_Object_Super()
{

    if( pMesh != NULL )
        pMesh->Release();

	if( pMeshMaterials != NULL ) 
        delete[] pMeshMaterials;

    if( pMeshTextures )
    {
        for( DWORD i = 0; i < dwNumMaterials; i++ )
        {
            if( pMeshTextures[i] )
                pMeshTextures[i]->Release();
        }
        delete[] pMeshTextures;
    }

	




};
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////

};// конец класса
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////	
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#endif //#ifndef GObject_h


